<?php
/**
 * Class UserInterface_Controller_TimeManagement
 */
class UserInterface_Controller_TimeManagement extends UserInterface_Controller_AbstractBase
{
    /**
     * @var Infrastructure_Mapper_Timelog
     */
    protected $timeLogMapper;

    /**
     * @param string $time
     * @return bool
     */
    protected function validateTime($time)
    {
        if (!preg_match('/\d\d:\d\d:\d\d/', $time, $matches)) {
            return false;
        }
        return true;
    }

    /**
     * @param int    $id
     * @param int    $timeUnix
     * @param bool   $enabled
     * @param string $name
     * @param string $enabledValue
     */
    protected function getCell($id, $timeUnix, $enabled, $name, $enabledValue)
    {
        echo '<td>';
        echo '<div class="button time' . (($enabled) ? ' enabled' : ' disabled') . '" data-name="' . $name . '" data-id="' . $id . '">';
        echo ($enabled) ? $enabledValue : date('H:i:s', $timeUnix);
        echo '</div>';
        echo '</td>';
    }

    /**
     *
     */
    public function run()
    {
        if ($this->inputProcessor->inPost('ajax')) {
            switch ($this->inputProcessor->post('action')) {
                case 'start':
                    $res = $this->_start($this->inputProcessor->post('id'), $this->inputProcessor->post('time'));
                    $this->renderAjaxResponseAndStop($res);
                    break;
                case 'start_lb':
                    $res = $this->_startLb($this->inputProcessor->post('id'), $this->inputProcessor->post('time'));
                    $this->renderAjaxResponseAndStop($res);
                    break;
                case 'end_lb':
                    $res = $this->_endLb($this->inputProcessor->post('id'), $this->inputProcessor->post('time'));
                    $this->renderAjaxResponseAndStop($res);
                    break;
                case 'end':
                    $res = $this->_end($this->inputProcessor->post('id'), $this->inputProcessor->post('time'));
                    $this->renderAjaxResponseAndStop($res);
                    break;
            }
            $this->renderAjaxResponseAndStop(array('error' => true, 'message' => 'Internal error!'));
        }

        // Pruefe, ob fuer heute ein Eintrag vorliegt
        $res = $this->timeLogMapper->findOneByByDate(date('Y-m-d', time()));

        // Sicherstellen, dass etwas zum Anzeigen da ist, und dass es nicht Wochenende ist
        // (ausser, wir geben das geheime Kennwort an).
        if (!$res && (((date('D') != 'Sat') && (date('D') != 'Sun')) || $this->inputProcessor->get('we'))) {
            // Neuen Eintrag erstellen
            $this->timeLogMapper->createNewEntryWithDate(date('Y-m-d', time()));
        }

        $dataArray = $this->getDataArray();

        $this->renderHeader('Zeitverwaltung');

        ?>
        <table class="table" border="0" style="">
            <thead>
            <tr>
                <th></th>
                <th>Start</th>
                <th>Mittagspause</th>
                <th>Mittagspause Ende</th>
                <th>Feierabend</th>
                <th>L&auml;nge Ohne Pause</th>
                <th>L&auml;nge Mittag</th>
                <th>Netto L&auml;nge</th>
                <th>Feierabend (gesch&auml;tzt)</th>
            </tr>
            </thead>
            <tr>
                <td style="height:1px;" colspan="9"></td>
            </tr>
            <tr>
                <td style="height:1px;" colspan="9"></td>
            </tr>
            <?php

            // loop through days
            krsort($dataArray);

            foreach ($dataArray as $id => $data) {
                $dataArray = $this->getTimeArray($data);
                ?>
                <tr>
                    <td colspan="9">
                        <table border="0" style="border-spacing: 0;">
                            <tr>
                                <td>
                                    <?php

                                    echo $data['date'];

                                    ?>
                                </td>
                                <?php
                                $this->getCell($id, $dataArray['start_unix'], $dataArray['start_enabled'], 'start', 'Start');
                                $this->getCell($id, $dataArray['start_lb_unix'], $dataArray['start_lb_enabled'], 'start_lb', 'Mittag');
                                $this->getCell($id, $dataArray['end_lb_unix'], $dataArray['end_lb_enabled'], 'end_lb', 'Mittag Ende');
                                $this->getCell($id, $dataArray['end_unix'], $dataArray['end_enabled'], 'end', 'Feierabend');

                                echo '</td><td id="total_nobreak_' . $id . '">';

                                echo ($dataArray['total_nobreak_unix'] > 0) ? implode(':', $dataArray['total_nobreak']) : '&nbsp;';
                                echo '</td><td id="break_' . $id . '">';

                                echo ($dataArray['break_unix'] > 0) ? implode(':', $dataArray['break']) : '&nbsp;';
                                echo '</td><td id="total_' . $id . '">';

                                echo ($dataArray['total_unix'] > 0) ? implode(':', $dataArray['total']) : '&nbsp;';
                                echo '</td><td id="home_' . $id . '">';

                                echo ($dataArray['break_unix'] > 0) ? implode(':', $dataArray['home']) : '&nbsp;';
                                ?>
                                </td>

                            </tr>
                        </table>

                    </td>
                </tr>

                <tr>
                    <td style="height:1px" colspan="9"></td>
                </tr>
            <?php
            }
            ?>
        </table>
        <script src="assets/js/timemanagement.js" type="text/javascript"></script>

        <?php
        $this->renderFooter();
    }

    /**
     * @param int $seconds
     * @return array
     */
    protected function formatDuration($seconds)
    {
        $periods = array(
            'centuries' => 3155692600,
            'decades'   => 315569260,
            'years'     => 31556926,
            'months'    => 2629743,
            'weeks'     => 604800,
            'days'      => 86400,
            'hours'     => 3600,
            'minutes'   => 60,
            'seconds'   => 1
        );
        $durations = array('hours' => 0, 'minutes' => 0, 'seconds' => 0);

        foreach ($periods as $period => $seconds_in_period) {
            if ($seconds >= $seconds_in_period) {
                $durations[$period] = floor($seconds / $seconds_in_period);
                $seconds -= $durations[$period] * $seconds_in_period;
            }
        }

        $durationsLZ = array();
        foreach ($durations as $key => $val) {
            $durationsLZ[$key] = sprintf("%02u", $val);
        }
        return $durationsLZ;
    }


    /**
     * @param array $data
     * @return array
     */
    protected function getTimeArray($data)
    {
        $dataArray = array();

        $dataArray['start_unix'] = 0;
        $dataArray['start_lb_unix'] = 0;
        $dataArray['end_lb_unix'] = 0;
        $dataArray['end_unix'] = 0;
        $dataArray['start_enabled'] = true;
        $dataArray['start_lb_enabled'] = true;
        $dataArray['end_lb_enabled'] = true;
        $dataArray['end_enabled'] = true;

        foreach ($data as $key => $val) {
            if (!isset($val['time'])) {
                continue;
            }
            if (!is_null($val['time'])) {
                $dataArray[$key . '_enabled'] = false;
            }

            $dataArray[$key . '_unix'] = strtotime($val['time']);
        }

        $dataArray['total_nobreak_unix'] = 0;
        $dataArray['break_unix'] = 0;
        $dataArray['total_unix'] = 0;
        $dataArray['total_nobreak'] = array();
        $dataArray['break'] = array();
        $dataArray['total'] = array();
        $dataArray['home'] = array();

        $dataArray['total_nobreak_unix'] = $dataArray['end_unix'] - $dataArray['start_unix'];
        $dataArray['total_nobreak'] = $this->formatDuration($dataArray['total_nobreak_unix']);
        $dataArray['break_unix'] = $dataArray['end_lb_unix'] - $dataArray['start_lb_unix'];
        $dataArray['break'] = $this->formatDuration($dataArray['break_unix']);
        $dataArray['total_unix'] = $dataArray['total_nobreak_unix'] - $dataArray['break_unix'];
        $dataArray['total'] = $this->formatDuration($dataArray['total_unix']);
        $midnight = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
        $dataArray['home'] = $this->formatDuration($dataArray['start_unix'] - $midnight + (8 * 60 * 60) + (36 * 60) + $dataArray['break_unix']);

        return $dataArray;
    }

    /**
     * @param null|int $id
     * @return array
     */
    protected function getDataArray($id = null)
    {
        // Daten-Array fuellen
        $dataArray = array();
        if (is_null($id)) {
            $res = $this->timeLogMapper->findLatestRecords();
        } else {
            $res = array($this->timeLogMapper->findOneByById($id));
        }

        foreach ($res as $data) {
            $dataArray[$data->id]['date'] = $data->date;
            $dataArray[$data->id]['start'] = array('time' => $data->start, 'date' => $data->date);
            $dataArray[$data->id]['start_lb'] = array('time' => $data->lunch, 'date' => $data->date);
            $dataArray[$data->id]['end_lb'] = array('time' => $data->lunchend, 'date' => $data->date);
            $dataArray[$data->id]['end'] = array('time' => $data->end, 'date' => $data->date);
        }

        return $dataArray;
    }

    /**
     * @param int    $id
     * @param string $time
     * @return array
     */
    protected function _start($id, $time)
    {
        if (!$this->validateTime($time)) {
            return array('error' => true, 'message' => 'Zeit ist ungueltig!');
        }

        $this->timeLogMapper->updateStartById($time, $id);

        $dataArray = $this->getDataArray($id);
        $timeArray = $this->getTimeArray($dataArray[$id]);

        return array(
            'error'         => false,
            'now'           => $time,
            'total_nobreak' => implode(':', $timeArray['total_nobreak']),
            'break'         => implode(':', $timeArray['break']),
            'total'         => implode(':', $timeArray['total']),
        );
    }

    /**
     * @param int $id
     * @return array
     */
    protected function _startLb($id, $time)
    {
        if (!$this->validateTime($time)) {
            return array('error' => true, 'message' => 'Zeit ist ungueltig!');
        }

        $this->timeLogMapper->updateLunchById($time, $id);

        $dataArray = $this->getDataArray($id);
        $timeArray = $this->getTimeArray($dataArray[$id]);

        return array(
            'error'         => false,
            'now'           => $time,
            'total_nobreak' => implode(':', $timeArray['total_nobreak']),
            'break'         => implode(':', $timeArray['break']),
            'total'         => implode(':', $timeArray['total']),
        );
    }

    /**
     * @param int    $id
     * @param string $time
     * @return array
     */
    protected function _endLb($id, $time)
    {
        if (!$this->validateTime($time)) {
            return array('error' => true, 'message' => 'Zeit ist ungueltig!');
        }

        $this->timeLogMapper->updateLunchEndById($time, $id);

        $dataArray = $this->getDataArray($id);
        $timeArray = $this->getTimeArray($dataArray[$id]);

        return array(
            'error'         => false,
            'now'           => $time,
            'total_nobreak' => implode(':', $timeArray['total_nobreak']),
            'break'         => implode(':', $timeArray['break']),
            'total'         => implode(':', $timeArray['total']),
            'home'          => implode(':', $timeArray['home']),
        );
    }

    /**
     * @param int    $id
     * @param string $time
     * @return array
     */
    protected function _end($id, $time)
    {
        if (!$this->validateTime($time)) {
            return array('error' => true, 'message' => 'Zeit ist ungueltig!');
        }

        $this->timeLogMapper->updateEndById($time, $id);

        // Calculate overtime!
        $this->timeLogMapper->calculateOvertimeById($id);

        $dataArray = $this->getDataArray($id);
        $timeArray = $this->getTimeArray($dataArray[$id]);

        return array(
            'error'         => false,
            'now'           => $time,
            'total_nobreak' => implode(':', $timeArray['total_nobreak']),
            'break'         => implode(':', $timeArray['break']),
            'total'         => implode(':', $timeArray['total']),
        );
    }

    /**
     * @param Infrastructure_Bootstrap $bootstrap
     */
    public function __construct(Infrastructure_Bootstrap $bootstrap)
    {
        parent::__construct($bootstrap);
        $this->timeLogMapper = $this->mapperFactory->createTimeLog();
    }
}